import React, { FC } from 'react'

// https://www.cnblogs.com/samve/p/12347658.html
// typescript 不过是 javascript 严格的语法模式  
// 所有的变量声明来源和类型 
// Typescript原始数据类型：
// string
// number
// boolean
// null
// undefined 
// enum   枚举类型 
// symbol    
// 空值一般采用void表示，void可以表示变量，也可以表示函数返回值。
// any 任意类型
// Array 数组  []
// Object 对象  {}



// 1.FC  React.FC是函数式组件，是在TypeScript使用的一个泛型，FC就是FunctionComponent的缩写，事实上React.FC可以写成React.FunctionComponent 
// 2.React.FC 包含了 PropsWithChildren 的泛型，不用显式的声明 props.children 的类型。React.FC<> 对于返回类型是显式的，而普通函数版本是隐式的（否则需要附加注释
// 3.React.FC提供了类型检查和自动完成的静态属性：displayName，propTypes和defaultProps（注意：defaultProps与React.FC结合使用会存在一些问题）。
// 4.我们使用React.FC来写 React 组件的时候，是不能用setState的，取而代之的是useState()、useEffect等 Hook API


// Typescript中对象类型-接口：  可描述类的一部分抽象行为，也可描述对象的结构形状。
// public  公有变量
//  private  私有变量
// protected 被保护的变量  
class Comment{
    constructor(
        public id:number,
        public title:string,
        public name:string,
        private uid:number
    ){

    }
}

const Demo:FC<any> = ()=> {

    let count:number = 100;
    let num:any = 50;
    let number = 1000;
    // number = "one"

    const one:string | boolean = "Are you Ok"
    const flag:Boolean = true;

    const obj:Object={};
    const list:Array<any> | any = [];

    interface Istate1{
        name:String,
        age:number,
    }
    const obj1:Istate1={
        name:"z1",
        age:19,
    }

    interface Istate2 {
        name:string
        age?: number;
       
    }
   const obj2:Istate2={
       name:"z2",
       age:29 ,
    }

// 属性个数不确定的时候，any必须是任意数据类型
interface Istate3{
    name:string |number;
    age?:number;
    [propsName:string]:any
}

const obj3:Istate3={
    name:'z3',
    age:18,
    sex:1,
    birth:6.1
}

// 只读属性
interface Istate4{
    name:string,  
    readonly age:number;
}
const obj4:Istate4 ={
    name:"z4",
    age:200
}
  // obj4.age = 18;  //只读属性，不可以被修改
 
//   type 类型定义
type ones ={
    id:number,
    name:string,
    age:number
}
const obj5:ones={
    id:1,
    name:"z5",
    age:19
}
console.log(obj5);

// Typescript 数组类型
// 1) 可以采用“类型[]”法表示
// 2） 可采用数组泛型“Arrary<类型>”表示法
// 3） 可采用接口表示法
const arr = [1,2,3,4]
const arr1:any =[1,2,3,4]
const arr2:Array<string> = ['1','2','3','4']
const arr3:Array<ones> =[{
    id:1,
    name:'z5',
    age:19
}]
const arr4:number[]=[1,2,3,4]
const arr5:ones[]=[{
    id:1, 
    name:'z5',
    age:19
}]
const arr6:Istate1[]=[{
    age:1,
    name:'z1'
}]

const arr7:Array<Comment> = [
     new Comment(1,'1',"1",1),
     new Comment(1,'1',"1",1),
]

  // 7、Typescript函数类型：
  // 函数约束：有函数本身的参数约束，返回值约束；
  // 还有函数本身赋值的变量的约束
  // 可采用重载的方式才支持联合类型的函数关系。

//   参数约束
function changeOne(id:number,age:number,name:string){
    return age + name;
}
changeOne(1,2,'3')

// 返回值约束
function  changeTwo():number{
    return 123;
}

// void 没有返回
function change():void {
    // return 123;
}

// 函数参数的默认值
function funType3(name = "Tom",age=18):number {
    return age;
}


// 表达式类型

function funType5(name="Tom",age=18):any {
   return name;
}

interface IfunType6{
    (name:string,age:number):number;
}

const funType6:IfunType6= function (name:string,age:number):number {
    return age;
}


// 类型断言可以用来手动指定一个值的类型

// 9、Typescript类型别名
type eventNames = "click" | "scroll" | "mousemove"

// 10 Typescript 
// 枚举枚举（enum）类型用于取值被限定在一定范围内的场景

//使用枚举可以定义一些有名字的数字常量
// 星期：星期一 到星期天
enum Days{
    Sun,
    Mon,
    Tue,
    Web,
    Thu,
    Fri,
    Sat
}
// 11、Typescript类的装饰符

// public 、 private 和 protected

// 12、Typescript泛型：

// 泛型是指在定义函数、接口或类的时候，不预定指定具体类型，而是在使用的时候再指定类型的一种特性
// 接口当中使用泛型

interface Icreate{
    <T>(name:string,value:T):Array<T>;
}

const func:Icreate = function <T>(name:string,value:T):Array<T> {
    return[];
}
const stArr2:number[] = func("Jack",3);
  return (
    <div>
        <h2>学习 typescript 语法</h2>
    </div>
  )
}

export default Demo